package com.yiji.fintech.musfinance.common.eventbus.listener.base;

import com.acooly.core.utils.enums.ResultStatus;
import com.acooly.core.utils.mapper.BeanCopier;
import com.yiji.fintech.musfinance.center.base.result.ResultFacade;
import com.yiji.fintech.musfinance.common.context.SpringApplicationContext;
import com.yiji.fintech.musfinance.common.domain.base.BaseDomain;
import com.yiji.fintech.musfinance.common.eventbus.event.base.BaseEvent;
import com.yiji.fintech.musfinance.common.exception.UniqueCheckException;
import com.yiji.fintech.musfinance.common.handler.UniqueServiceHandler;
import com.yiji.fintech.musfinance.common.strategy.base.UniqueBaseStrategy;
import com.yiji.fintech.musfinance.common.strategy.context.UniqueContext;
import lombok.extern.slf4j.Slf4j;

/**
 * Created by ouwen@yiji.com} on 2017/9/18.
 */
@Slf4j
public abstract class AbstractCommonListener<T extends BaseEvent,R extends BaseDomain> extends UniqueServiceHandler implements ListenerBase<R>{
    /**
     * 订阅消息
     * @param event
     */
    public void doExcute(T event){
        ResultFacade result = event.getResult();
        result.setGid(event.getDomain().getGid());
        result.setMerchOrderNo(event.getDomain().getMerchOrderNo());
        result.setBizOrderNo(event.getDomain().getBizOrderNo());
        try {
            process(event);
        }catch (UniqueCheckException e){
            result.setStatus(event.getResult().getStatus());
            result.setCode(event.getResult().getCode());
            result.setDetail(event.getResult().getDetail());
        }catch (Exception e) {
            result.setStatus(ResultStatus.failure);
            result.setCode(ResultStatus.failure.getCode());
            if (e instanceof RuntimeException) {
                result.setDetail(e.getMessage());
            } else {
                result.setDetail("未知异常");
            }
            log.error("调度中心业务异常",e);
        }
    }
    /**
     * 发送网关
     * @param domain
     * @param result
     */
    protected abstract void sendgetway(BaseDomain domain, ResultFacade result);
    /**
     * 统一处理流程，如果业务流程不同覆盖此方法
     * @param event
     */
    public void process(T event){
        BaseDomain domain = event.getDomain();
        ResultFacade result = event.getResult();
        unique((R) domain,result);//唯一性校验
        channelRoute((R) domain);//路由规则
        initTransaction(domain);//初始化流水相关信息
        insertTransAction((R) domain);//记录流水
        sendgetway(domain,result);//发送网关
        updateTransAction((R) domain);//更新流水
    }

    /**
     * 初始化流水信息
     * @param domain
     */
    protected abstract void initTransaction(BaseDomain domain);

    /**
     * 渠道路由
     * @param domain
     */
    @Override
    public  void channelRoute(R domain){
        getSuperRouteService().channel(domain);
    }
    @Override
    public void insertTransAction(R domain) {
        initEntity(domain);
        service.save(entity);
    }

    @Override
    public void unique(R domain,ResultFacade result) {
        UniqueBaseStrategy uniqueStrategy = (UniqueBaseStrategy) SpringApplicationContext.getBeanByName("commonUniqueStrategy");
        UniqueContext uniqueContext = new UniqueContext(uniqueStrategy);
        uniqueContext.doUnique(domain,result);
    }

    @Override
    public void updateTransAction(R domain) {
        findEntity(domain);
        BeanCopier.copy(domain,entity,BeanCopier.CopyStrategy.IGNORE_NULL, BeanCopier.NoMatchingRule.IGNORE,null);
        service.update(entity);
    }
}
